package com.iwdnb.gkgz.controller;

import java.awt.*;
import java.math.BigDecimal;
import java.net.URI;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;

import cn.hutool.core.date.DateUtil;
import com.google.common.collect.Lists;
import com.iwdnb.bmnf.common.model.OrderBy;
import com.iwdnb.bmnf.common.model.result.Result;
import com.iwdnb.bmnf.common.utils.BooleanUtils;
import com.iwdnb.gkgz.application.service.StockLimitUpService;
import com.iwdnb.gkgz.application.service.TulongdaoService;
import com.iwdnb.gkgz.common.model.dto.Stock;
import com.iwdnb.gkgz.common.model.dto.StockDayData;
import com.iwdnb.gkgz.common.model.dto.StockRangeScopeDTO;
import com.iwdnb.gkgz.common.model.dto.StockSignalDTO;
import com.iwdnb.gkgz.common.quota.MovingAverage;
import com.iwdnb.gkgz.common.utils.BigDecimalUtils;
import com.iwdnb.gkgz.common.utils.StockAverageUtils;
import com.iwdnb.gkgz.common.utils.StockAverageUtils.StepBackAverage;
import com.iwdnb.gkgz.common.utils.StockBlackListUtils;
import com.iwdnb.gkgz.common.utils.StockUtils;
import com.iwdnb.gkgz.common.utils.WorkDayUtils;
import com.iwdnb.gkgz.infrastructure.dao.repo.StockDayDataRepository;
import com.iwdnb.gkgz.infrastructure.dao.repo.impl.StockDayDataLocalRepositoryImpl;
import com.iwdnb.wwzy.dao.MetaDataDAO;
import com.iwdnb.wwzy.model.query.MetaQuery;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import static com.iwdnb.gkgz.common.constant.GkgzConstants.OBJECT_CODE_STOCK_SIGNAL;

/**
 * 测试
 **/
@RestController
@RequestMapping("/api/stock/test")
@Slf4j
public class TestController {
    @Autowired
    private TulongdaoService tulongdaoService;
    @Autowired
    private StockLimitUpService stockLimitUpService;
    @Autowired
    private Executor executor;
    @Autowired
    private MetaDataDAO metaDataDAO;
    @Autowired
    private StockDayDataRepository stockDayDataRepository;
    @Autowired
    private StockDayDataLocalRepositoryImpl stockDayDataLocalRepository;

    @RequestMapping("/doSignalBackTest")
    public Result<String> doSignalBackTest() {
        String orderField = "two_month_later_high_rate";
        String sort = "asc";
        MetaQuery metaQuery = new MetaQuery();
        metaQuery.setOrder(new OrderBy(orderField, sort));
        metaQuery.addParam("winFlag", "n");
        List<StockSignalDTO> stockSignalDTOList = metaDataDAO.queryListByCondition(OBJECT_CODE_STOCK_SIGNAL, metaQuery,
            StockSignalDTO.class);
        if (CollectionUtils.isEmpty(stockSignalDTOList)) {
            return Result.getErrorResult("股票信号数据为空");
        }
        for (StockSignalDTO stockSignalDTO : stockSignalDTOList) {
            signalBackTest(stockSignalDTO);
        }
        return Result.getSuccessResult(null);
    }

    /**
     * 日k线初始化,后续本地电脑上跑测试时可以调用本地数据获取日k数据,参数设置:gkgz.db.storeType=local
     *
     * @return
     */
    @RequestMapping("/initStockDayDataToLocal")
    public Result<String> stockDayDataToLocal() {
        stockDayDataLocalRepository.initStockDayDataToLocal();
        return Result.getSuccessResult(null);
    }


    /**
     * 保存情绪图
     *
     * @return
     */
    @RequestMapping("/testSaveEmotionImage")
    public Result<String> testSaveEmotionImage() {
        Date now = new Date();
        String url = "http://root.com:8001/api/stock/chart/stockEmotionSaveImage?date=" + DateUtil.formatDate(now);
        try {
            Desktop.getDesktop().browse(new URI(url));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Result.getSuccessResult(null);
    }


    private void signalBackTest(StockSignalDTO stockSignalDTO) {
        Integer period = 20;
        Integer longPeriod = 60;
        Integer yearPeriod = 250;
        String code = stockSignalDTO.getCode();
        List<StockDayData> stockDayDataList = stockDayDataRepository.queryAll(code);
        MovingAverage.calculateEMA(stockDayDataList, period);
        MovingAverage.calculateEMA(stockDayDataList, longPeriod);
        MovingAverage.calculateEMA(stockDayDataList, yearPeriod);
        Date d = stockSignalDTO.getSignalDate();
        String date = DateUtil.formatDate(d);
        StockDayData yesterdayData = StockUtils.getYesterdayStockDayData(stockDayDataList, date);
        StockDayData stockDayData = StockUtils.getStockDayData(stockDayDataList, date);
        stockDayDataList = StockUtils.getStockDayDataListAfterDate(stockDayDataList, date, 120);
        stockDayDataList.add(0, stockDayData);
        if (Objects.isNull(yesterdayData)) {
            log.info("{}-无昨日数据", code);
            return;
        }
        stepBackAverage(code, stockDayData, yesterdayData, stockDayDataList, period, "20日均线", stockSignalDTO);
        stepBackAverage(code, stockDayData, yesterdayData, stockDayDataList, longPeriod, "60日均线", stockSignalDTO);
        stepBackAverage(code, stockDayData, yesterdayData, stockDayDataList, yearPeriod, "年均线", stockSignalDTO);
    }

    private void stepBackAverage(String code, StockDayData stockDayData, StockDayData yesterdayData,
        List<StockDayData> stockDayDataList, int period, String periodName, StockSignalDTO stockSignalDTO) {
        StepBackAverage stepBackAverage = StockAverageUtils.getStepBack(code, stockDayData, yesterdayData,
            stockDayDataList, period);
        if (!stepBackAverage.isFallBackFlag()) {
            return;
        }

        String endDate = stockDayDataList.get(stockDayDataList.size() - 1).getDate();
        if (StringUtils.isNotBlank(stepBackAverage.getUpBackDate())) {
            List<StockDayData> subList = StockUtils.getStockDayDataListAfterDate(stockDayDataList,
                stepBackAverage.getUpBackDate(), 40);
            StockRangeScopeDTO rangeScopeDTO = StockUtils.getRangeScopeByDateRange(subList,
                stepBackAverage.getUpBackDate(), endDate);
            if (Objects.isNull(rangeScopeDTO)) {
                StockDayData data = StockUtils.getStockDayData(stockDayDataList, stepBackAverage.getUpBackDate());
                rangeScopeDTO = StockUtils.flatRangeScope(data);
            }
            BigDecimal lowRate = BigDecimalUtils.subStractAndDividePrecent(rangeScopeDTO.getLowPrice(),
                stepBackAverage.getUpBackPrice());
            BigDecimal highRate = BigDecimalUtils.subStractAndDividePrecent(rangeScopeDTO.getHighPrice(),
                stepBackAverage.getUpBackPrice());
            log.info("{}({})-{}回踩{}-{},间隔{}天于{}-{}重新站上均线,后续最低价日期:{},跌幅:{},最高日期:{},涨幅:{}", code,
                stockSignalDTO.getSignalDate(), DateUtil.formatDate(stockSignalDTO.getSignalDate()),
                stepBackAverage.getFallBackPrice(), periodName, stepBackAverage.getInterval(),
                stepBackAverage.getUpBackDate(), stepBackAverage.getUpBackPrice(), rangeScopeDTO.getLowDate(), lowRate,
                rangeScopeDTO.getHighDate(), highRate);
        } else {
            List<StockDayData> subList = StockUtils.getStockDayDataListAfterDate(stockDayDataList,
                stepBackAverage.getFallBackDate(), 40);
            StockRangeScopeDTO rangeScopeDTO = StockUtils.getRangeScopeByDateRange(subList,
                stepBackAverage.getFallBackDate(), endDate);
            if (Objects.isNull(rangeScopeDTO)) {
                StockDayData data = StockUtils.getStockDayData(stockDayDataList, stepBackAverage.getFallBackDate());
                rangeScopeDTO = StockUtils.flatRangeScope(data);
            }
            BigDecimal lowRate = BigDecimalUtils.subStractAndDividePrecent(rangeScopeDTO.getLowPrice(),
                stepBackAverage.getFallBackPrice());
            BigDecimal highRate = BigDecimalUtils.subStractAndDividePrecent(rangeScopeDTO.getHighPrice(),
                stepBackAverage.getFallBackPrice());
            log.info("{}({})-{}-{}回踩{},后续未重新站上均线,后续最低价日期:{},跌幅:{},最高日期:{},涨幅:{}", code,
                DateUtil.formatDate(stockSignalDTO.getSignalDate()), stepBackAverage.getFallBackDate(),
                stepBackAverage.getFallBackPrice(), periodName, rangeScopeDTO.getLowDate(), lowRate,
                rangeScopeDTO.getHighDate(), highRate);
        }
    }
}
